package net.wisedream.littletools.jff;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import net.wisedream.littletools.jff.util.HttpClientFactory;
import net.wisedream.littletools.jff.util.HttpClientHelper;
import net.wisedream.littletools.jff.util.StringUtils;
import net.wisedream.littletools.jff.xml.Action.Headers;
import net.wisedream.littletools.jff.xml.Actions;
import net.wisedream.littletools.jff.xml.Actions.Action;
import net.wisedream.littletools.jff.xml.JustForFun;
import net.wisedream.littletools.jff.xml.Settings;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Hello world!
 * 
 */
public class App {
	private static Logger log = LoggerFactory.getLogger("app");

	public static void main(String[] args) {
		try {
			File configFile = new File(args[0]);
			if (!configFile.exists() || configFile.isDirectory())
				throw new Exception(
						"ConfigFile doesn't exist or is not a file.");
			JustForFun config = unmarshal(JustForFun.class,
					new FileInputStream(configFile));
			haveFun(config);
		} catch (Exception e) {
			if (e instanceof IndexOutOfBoundsException)
				log.error("Usage java -jar JustForFun.jar <ConfigFile>");
			else
				log.error(e.getMessage(), e);
		}
	}
	private static <T> T unmarshal(Class<T> docClass, InputStream inputStream)
			throws JAXBException {
		String packageName = docClass.getPackage().getName();
		JAXBContext jc = JAXBContext.newInstance(packageName);
		Unmarshaller u = jc.createUnmarshaller();
		JAXBElement<T> doc = (JAXBElement<T>) u.unmarshal(inputStream);
		return doc.getValue();
	}
	private static void haveFun(JustForFun config)
			throws UnsupportedEncodingException {
		Settings settings = config.getSettings();
		HttpClient httpClient = HttpClientFactory.getHttpClient(false,
				settings.getConnectionTimeout(), settings.getSocketTimeout());
		if (!settings.getProxy().equalsIgnoreCase("none"))
			HttpClientHelper.setProxy(httpClient, settings.getProxy());
		Actions actions = config.getActions();
		for (Action action : actions.getAction()) {
			log.info("Executing Action: " + action.getName());
			doRequest(httpClient, action);
		}
	}
	private static void doRequest(HttpClient httpClient, Action action)
			throws UnsupportedEncodingException {
		HttpUriRequest request = null;
		// uri+body
		if (action.getMethod().equalsIgnoreCase("POST")) {
			HttpPost postRequest = new HttpPost(action.getUrl());
			if (!StringUtils.isNullOrEmpty(action.getBody()))
				postRequest.setEntity(new StringEntity(action.getBody()
						.replace("${timestamp}",
								String.valueOf(System.currentTimeMillis())),
						action.getCharset()));
			request = postRequest;
		} else {
			request = new HttpGet(action.getUrl());
		}
		// headers
		if (action.getHeaders() != null) {
			for (Headers.Header header : action.getHeaders().getHeader())
				request.setHeader(header.getKey(), header.getValue());
		}
		// temp proxy
		String origProxy = HttpClientHelper.getProxy(httpClient);
		boolean tempProxy = !action.getProxy().equalsIgnoreCase("none");
		if (tempProxy)
			HttpClientHelper.setProxy(httpClient, action.getProxy());
		HttpResponse response = null;
		try {
			response = httpClient.execute(request);
			log.info("\tStatusCode: "
					+ response.getStatusLine().getStatusCode());
			if (log.isDebugEnabled()) {
				String resp = HttpClientHelper.readContent(response, action.getCharset());
				log.debug("\t" + resp);
			}
		} catch (Exception e) {
			log.warn("\tError Occurred", e);
			request.abort();
		} finally {
			if (response != null)
				EntityUtils.consumeQuietly(response.getEntity());
			if (tempProxy)
				HttpClientHelper.setProxy(httpClient, origProxy);
		}
	}
}
